/*
' Copyright (c) 2011 DotNetNuke Corporation
'  All rights reserved.
'
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
' TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
' CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
' DEALINGS IN THE SOFTWARE.
'
*/

using System;
using System.Globalization;
using System.Transactions;
using System.Web.UI.WebControls;
using DotNetNuke.Common;
using DotNetNuke.Entities.Users;
using DotNetNuke.Modules._2DoTasks.Components;
using DotNetNuke.Modules._2DoTasks.Components.Controllers;
using DotNetNuke.Modules._2DoTasks.Components.Entities;
using DotNetNuke.Modules._2DoTasks.Components.ExceptionHandling;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;

namespace DotNetNuke.Modules._2DoTasks
{
    /// -----------------------------------------------------------------------------
    /// <summary>
    /// The Edit_2DoTasks class is used to manage content
    /// </summary>
    /// -----------------------------------------------------------------------------
    public partial class Task : _2DoTasksModuleBase
    {
        #region Event Handlers

        override protected void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);
        }

        private void InitializeComponent()
        {
            this.Load += new System.EventHandler(this.Page_Load);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Page_Load runs when the control is loaded
        /// </summary>
        /// -----------------------------------------------------------------------------
        private void Page_Load(object sender, System.EventArgs e)
        {
            try
            {
                this.Messages.ClearMessages();
                FillLanguages();

                //Implement your edit logic for your module
                if (!Page.IsPostBack)
                {
                    //fill controls

                    FillControls();

                    if (TaskId.HasValue)
                    {
                        BindTask(TaskId.Value);
                    }
                    else
                    {
                        txt_assignedTo.Text = txt_requestedBy.Text = UserInfo.Username;
                    }
                }
            }
            catch (Exception exc) //Module failed to load
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
        }

        /// <summary>
        /// Adds/Updates an existing task
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btn_send_Click(object sender, EventArgs e)
        {
            Nullable<DateTime> targetcompletionDate;
            Nullable<int> projectId = null;
            int? assignedUserId = null;
            int? requestedByUserId = null;

            if (Page.IsValid)
            {
                try
                {
                    using (UnitOfWork uof = new UnitOfWork(PortalId, ModuleId))
                    {
                        if (TaskParametersAreCorrectlyFilled(uof, out targetcompletionDate, out projectId, out assignedUserId, out requestedByUserId))
                        {
                            TaskController taskController = new TaskController(uof);

                            //Set task fields
                            _Task task = new _Task
                            {
                                Name = txt_Name.Text.Trim(),
                                AssignedUserId = assignedUserId,
                                RequestedByUserId = requestedByUserId.Value,
                                TargetCompletiondate = targetcompletionDate,
                                TaskType = Convert.ToInt16(drp_taskType.SelectedValue),
                                TaskStatus = Convert.ToInt16(drp_taskStatus.SelectedValue),
                                Priority = Convert.ToInt16(drp_taskPriority.SelectedValue),
                                ProjectId = projectId,
                                Description = txt_description.Text.Trim()
                            };
                            using (TransactionScope scope = new TransactionScope())
                            {
                                if (TaskId.HasValue)
                                {
                                    task.TaskId = TaskId.Value;
                                    taskController.Update(task);
                                    if (!TaskComments.Comment.Equals(string.Empty))
                                        TaskComments.SaveTaskComment(uof);
                                }
                                else
                                {
                                    taskController.Add(task);
                                }
                                scope.Complete();
                            }

                            //redirect user
                            if (TaskId.HasValue)
                                Response.Redirect(Globals.NavigateURL(string.Empty, string.Empty, "tsk=2"));
                            else
                                Response.Redirect(Globals.NavigateURL(string.Empty, string.Empty, "tsk=1"));
                        }
                    }
                }
                catch (TaskCommentValidationException exc)
                {
                    TaskCommentController.InsertStatus status =
                            (TaskCommentController.InsertStatus)Enum.Parse(typeof(TaskCommentController.InsertStatus), exc.ErrorCode().ToString());

                    switch (status)
                    {
                        case TaskCommentController.InsertStatus.USERCANNOTMODIFYTASK:
                            Messages.ShowWarning(Localization.GetString("WarningUSERCANNOTMODIFYTASK", this.LocalResourceFile));
                            break;

                        default:
                            Exceptions.LogException(exc);
                            Messages.ShowError(Localization.GetString("ErrorAddTask", this.LocalResourceFile));
                            break;
                    }
                }
                catch (TaskValidationException exc)
                {
                    if (exc.StateOfError() == SharedEnum.CrudState.Insert)
                    {
                        TaskController.InsertStatus status =
                            (TaskController.InsertStatus)Enum.Parse(typeof(TaskController.InsertStatus), exc.ErrorCode().ToString());

                        switch (status)
                        {
                            case TaskController.InsertStatus.CREATORNOTMEMBER:
                                Messages.ShowWarning(Localization.GetString("WarningCREATORNOTMEMBER", this.LocalResourceFile));
                                break;

                            case TaskController.InsertStatus.ASSIGNEDNOTMEMBER:
                                Messages.ShowWarning(Localization.GetString("WarningASSIGNEDNOTMEMBER", this.LocalResourceFile));
                                break;

                            case TaskController.InsertStatus.PROJECTNOTFOUND:
                                Messages.ShowWarning(Localization.GetString("WarningProjectNotFound", this.LocalResourceFile));
                                break;

                            case TaskController.InsertStatus.INVALIDASSIGNEDUSER:
                                Messages.ShowWarning(Localization.GetString("WarningINVALIDASSIGNEDUSER", this.LocalResourceFile));
                                break;

                            default:
                                Exceptions.LogException(exc);
                                Messages.ShowError(Localization.GetString("ErrorAddTask", this.LocalResourceFile));
                                break;
                        }
                    }
                    else if (exc.StateOfError() == SharedEnum.CrudState.Update)
                    {
                        TaskController.UpdateStatus status =
                            (TaskController.UpdateStatus)Enum.Parse(typeof(TaskController.UpdateStatus), exc.ErrorCode().ToString());

                        switch (status)
                        {
                            case TaskController.UpdateStatus.CREATORNOTMEMBER:
                                Messages.ShowWarning(Localization.GetString("WarningCREATORNOTMEMBER", this.LocalResourceFile));
                                break;

                            case TaskController.UpdateStatus.PROJECTNOTFOUND:
                                Messages.ShowWarning(Localization.GetString("WarningProjectNotFound", this.LocalResourceFile));
                                break;

                            case TaskController.UpdateStatus.ASSIGNEDNOTMEMBER:
                                Messages.ShowWarning(Localization.GetString("WarningASSIGNEDNOTMEMBER", this.LocalResourceFile));
                                break;

                            case TaskController.UpdateStatus.CANNOTSETEMPTYPROJECT:
                                Messages.ShowWarning(Localization.GetString("WarningCANNOTSETEMPTYPROJECT", this.LocalResourceFile));
                                break;

                            case TaskController.UpdateStatus.INVALIDASSIGNEDUSER:
                                Messages.ShowWarning(Localization.GetString("WarningINVALIDASSIGNEDUSER", this.LocalResourceFile));
                                break;

                            case TaskController.UpdateStatus.LASTCHANGEUSERNOTMEMBER:
                                Messages.ShowWarning(Localization.GetString("WarningLASTCHANGEUSERNOTMEMBER", this.LocalResourceFile));
                                break;

                            default:
                                Exceptions.LogException(exc);
                                Messages.ShowError(Localization.GetString("ErrorUpdateTask", this.LocalResourceFile));
                                break;
                        }
                    }
                }
                catch (Exception exc)
                {
                    if (TaskId.HasValue)
                        this.Messages.ShowError(Localization.GetString("ErrorUpdateTask", this.LocalResourceFile));
                    else
                        this.Messages.ShowError(Localization.GetString("ErrorAddTask", this.LocalResourceFile));

                    Exceptions.LogException(exc);
                }
            }
        }

        /// <summary>
        /// Close without making changes
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btn_cancel_Click(object sender, EventArgs e)
        {
            Response.Redirect(Globals.NavigateURL());
        }

        #endregion Event Handlers

        #region "Aux Functions"

        /// <summary>
        /// Evaluates if the fields for creating a new task are correctly filled
        /// </summary>
        /// <returns>returns true, if ok, false otherwise</returns>
        private bool TaskParametersAreCorrectlyFilled(
            UnitOfWork uof,
            out DateTime? out_targetcompletionDate,
            out int? out_projectId,
            out int? out_assignedToUserId,
            out int? out_verifiedByUserId)
        {
            out_targetcompletionDate = null;
            out_projectId = out_assignedToUserId = out_verifiedByUserId = null;

            if (txt_Name.Text.Trim().Equals(string.Empty))
            {
                Messages.ShowWarning(Localization.GetString("ValidationNameRequired", this.LocalResourceFile));
                return false;
            }

            if (txt_Name.Text.Length < 2)
            {
                Messages.ShowWarning(Localization.GetString("ValidationNameMinLenght", this.LocalResourceFile));
                return false;
            }

            //if project field is passed, get the project id
            if (!txt_Project.Text.Trim().Equals(string.Empty))
            {
                //get the project with the passed name, so it can be associated to the task
                ProjectController prjController = new ProjectController(uof);
                _Project project = prjController.Get(txt_Project.Text.Trim());
                if (project == null)
                {
                    Messages.ShowWarning(Localization.GetString("WarningProjectNotFound", this.LocalResourceFile));
                    return false;
                }
                out_projectId = project.ProjectId;
            }

            //verify assigned to user
            if (!txt_assignedTo.Text.Trim().Equals(string.Empty))
            {
                //verify by name
                UserInfo userInfo = UserController.GetUserByName(PortalId, txt_assignedTo.Text.Trim());
                if (userInfo == null)
                {
                    Messages.ShowWarning(Localization.GetString("WarningAssignedToNotFound", this.LocalResourceFile));
                    return false;
                }
                else
                    out_assignedToUserId = userInfo.UserID;
            }

            //requested by user is required
            if (txt_requestedBy.Text.Trim().Equals(string.Empty))
            {
                Messages.ShowWarning(Localization.GetString("ValidationRequestedByRequired", this.LocalResourceFile));
                return false;
            }
            else
            {
                //verify by name
                UserInfo userInfo = UserController.GetUserByName(PortalId, txt_requestedBy.Text.Trim());
                if (userInfo == null)
                {
                    Messages.ShowWarning(Localization.GetString("WarningRequestedByNotFound", this.LocalResourceFile));
                    return false;
                }
                else
                    out_verifiedByUserId = userInfo.UserID;
            }

            if (txt_targetCompletiondate.Text != string.Empty)
            {
                try
                {
                    CultureInfo provider = CultureInfo.InvariantCulture;

                    out_targetcompletionDate = DateTime.ParseExact(txt_targetCompletiondate.Text, "dd-MM-yyyy", provider);
                }
                catch (Exception)
                {
                    Messages.ShowWarning(Localization.GetString("ValidationInvalidDate", this.LocalResourceFile));
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Binds the received task id to the respective controls
        /// </summary>
        private void BindTask(int taskId)
        {
            using (UnitOfWork uof = new UnitOfWork(PortalId, ModuleId))
            {
                _Task task = new TaskController(uof).Get(taskId);
                if (task != null)
                {
                    txt_Name.Text = task.Name;
                    if (task.ProjectId.HasValue)
                        txt_Project.Text = task.ProjectName;
                    txt_description.Text = task.Description;
                    if (task.TargetCompletiondate.HasValue)
                        txt_targetCompletiondate.Text = task.TargetCompletiondate.Value.ToString("dd-MM-yyyy");
                    if (task.AssignedUserId.HasValue)
                        txt_assignedTo.Text = task.AssignedUser.Username;
                    txt_requestedBy.Text = task.RequestedByUser.Username;
                    drp_taskPriority.SelectedValue = task.Priority.ToString();
                    drp_taskStatus.SelectedValue = task.TaskStatus.ToString();
                    drp_taskType.SelectedValue = task.TaskType.ToString();
                    this.TaskComments.Visible = true;
                    this.TaskTimeEntries.Visible = true;
                    this.TaskSubTasks.Visible = true;
                }
                else
                {
                    Response.Redirect(Globals.NavigateURL(string.Empty, string.Empty));
                }
            }
        }

        /// <summary>
        /// Fills module controls
        /// </summary>
        private void FillControls()
        {
            //set priotities
            Array enumPr = System.Enum.GetValues(typeof(SharedEnum.TaskPriority));

            foreach (SharedEnum.TaskPriority option in enumPr)
            {
                drp_taskPriority.Items.Add(
                    new ListItem(Localization.GetString(option.ToString(), this.LocalResourceFile),
                                 ((int)option).ToString()));
            }

            //set status
            Array enumSt = System.Enum.GetValues(typeof(SharedEnum.TaskStatus));

            foreach (SharedEnum.TaskStatus option in enumSt)
            {
                drp_taskStatus.Items.Add(
                    new ListItem(Localization.GetString(option.ToString(), this.LocalResourceFile),
                                 ((int)option).ToString()));
            }

            //set task type

            Array enumTp = System.Enum.GetValues(typeof(SharedEnum.TaskType));

            foreach (SharedEnum.TaskType option in enumTp)
            {
                drp_taskType.Items.Add(
                    new ListItem(Localization.GetString(option.ToString(), this.LocalResourceFile),
                                 ((int)option).ToString()));
            }
        }

        /// <summary>
        /// Fills the language data into the respective controls
        /// </summary>
        private void FillLanguages()
        {
            btn_send.Text = Localization.GetString("btn_send", this.LocalResourceFile);
            btn_cancel.Text = Localization.GetString("btn_cancel", this.LocalResourceFile);

            txt_Name.CssClass = string.Concat("validate:{required:true, minlength: 2, messages:{required:'",
                                               Localization.GetString("ValidationNameRequired", this.LocalResourceFile),
                                                    "', minlength:'",
                                                    Localization.GetString("ValidationNameMinLenght", this.LocalResourceFile),
                                                    "'}}");

            txt_requestedBy.CssClass = string.Concat("validate:{required:true, messages:{required:'",
                                               Localization.GetString("ValidationRequestedByRequired", this.LocalResourceFile),
                                                    "'}}");
        }

        #endregion "Aux Functions"
    }
}